package com.study.thread.juc.lock;

import java.util.concurrent.CountDownLatch;

/*
    CountDownLatch：是一个线程同步的计数器，当某一个线程调用await()时如果没有线程之前调用down()将计数器变为0，则调用await()方法被阻塞；
            await()：阻塞线程运行，直到计数器为0被唤醒
            down()：线程将计数器-1，假如是计数器是2，线程调用down()，计数器则变为1，等待另一个线程调用到0时，会释放阻塞线程

          总结：同一时刻只能有一个线程调用await()方法，多个线程调用会造成阻塞，也就是说线程A调用了await()，则线程B需要的等线程A唤醒后调用
                因为在释放的时候，只会唤醒一个线程，所以多个线程调用被唤醒一个线程，其余线程则会阻塞不会被唤醒，当所有线程调用完后计数器为0，
                其余线程在调用await()方法是直接返回的，不会被阻塞了，也就是说CountDownLatch的作用是一次性的！
 */
public class CountDownLatch2Demo {
    private static CountDownLatch countDownLatch1 = new CountDownLatch(3);

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "：开始执行");
                System.out.println(Thread.currentThread().getName() + "：结束");
            } finally {
                countDownLatch1.countDown();
                System.out.println(Thread.currentThread().getName() + "：释放");
            }
        }).start();


        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "：开始执行");
                System.out.println(Thread.currentThread().getName() + "：结束");
            } finally {
                countDownLatch1.countDown();
                System.out.println(Thread.currentThread().getName() + "：释放");
            }
        }).start();
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "：开始执行");
                System.out.println(Thread.currentThread().getName() + "：结束");
            } finally {
                countDownLatch1.countDown();
                System.out.println(Thread.currentThread().getName() + "：释放");
            }
        }).start();
        System.out.println("主方法，开始阻塞");
        countDownLatch1.await();
        System.out.println("主方法，运行结束");

    }
}
